package com.ds.robot.assistant.service.yunxiao;

import com.alibaba.fastjson.JSON;
import com.aliyun.sdk.service.devops20210625.models.*;
import com.google.common.collect.Lists;
import com.ds.robot.assistant.enums.Env;
import com.ds.robot.assistant.enums.WorkItemCategoryEnum;
import com.ds.robot.assistant.model.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * 作用：
 * <p>
 * <p>
 * GET /organization/{organizationId}/listProjects 获取项目列表
 *
 * @author WeiShaoying
 * 
 */
@Component
@Slf4j
@SuppressWarnings("ALL")
public class YunXiaoBugClient extends YunXiaoBase {

    /**
     * 查询缺陷报告消息
     *
     * @return
     */
    public List<YxProjectBug> queryProjectBugList() {
        long start = System.currentTimeMillis();
        List<YxProjectBug> projectBugList = Lists.newArrayList();

        List<CompletableFuture<ListWorkitemsResponse>> futureList = Lists.newArrayList();

        Map<String, String> projectMap = getProjectMap();

        for (Map.Entry<String, String> entry : projectMap.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            log.info("====开始处理：{}", value);
            ListWorkitemsRequest listWorkitemsRequest = ListWorkitemsRequest.builder()
                    .organizationId(ORGANIZATION_ID)
                    .spaceType(STR_PROJECT)
                    .spaceIdentifier(key)
                    .category(WorkItemCategoryEnum.Bug.name())
                    .maxResults(MAX_RESULTS)
                    .conditions("{\"conditionGroups\":[[{\"fieldIdentifier\":\"status\",\"operator\":\"CONTAINS\",\"value\":[\"30\",\"100005\",\"28\",\"100010\",\"32\",\"142838\"],\"toValue\":null,\"className\":\"status\",\"format\":\"list\"}]]}")
                    // Request-level configuration rewrite, can set Http request parameters, etc.
                    // .requestConfiguration(RequestConfiguration.create().setHttpHeaders(new HttpHeaders()))
                    .build();
            // Asynchronously get the return value of the API request
            CompletableFuture<ListWorkitemsResponse> response = asyncClient.listWorkitems(listWorkitemsRequest);
            futureList.add(response);
        }

        CompletableFuture<List<ListWorkitemsResponse>> allResultList = CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0]))
                .thenApply(v -> futureList.stream().map(CompletableFuture::join).filter(Objects::nonNull)
                        .collect(Collectors.toList()))
                .exceptionally(throwable -> {
                    throwable.printStackTrace();
                    return null;
                });
        List<ListWorkitemsResponse> projectResponseList = allResultList.join();

        // 遍历项目
        for (ListWorkitemsResponse response : projectResponseList) {
            if (response.getBody() == null || CollectionUtils.isEmpty(response.getBody().getWorkitems())) {
                continue;
            }

            String spaceIdentifier = response.getBody().getWorkitems().get(0).getSpaceIdentifier();
            String spaceName = response.getBody().getWorkitems().get(0).getSpaceName();

            //当前项目下Bug数量
            Long count = response.getBody().getTotalCount();

            if (count != null && count > 0) {
                List<String> idList = response.getBody().getWorkitems().stream().map(ListWorkitemsResponseBody.Workitems::getIdentifier).collect(Collectors.toList());
                log.debug("{}: bugIdList = {}", response.getBody().getWorkitems().get(0).getSpaceName(), JSON.toJSONString(idList));
                // 查询工作项，获得标签信息
                List<GetWorkItemInfoResponse> workItemInfoResponseList = getGetWorkItemInfoResponse(idList);

                List<YxBug> bugList = workItemInfoResponseList.stream().map(GetWorkItemInfoResponse::getBody).map(GetWorkItemInfoResponseBody::getWorkitem)
                        .map(item -> {
                                    YxBug yxBug = new YxBug(item.getIdentifier(), item.getAssignedTo(), item.getStatus());
                                    String tagName = Optional.ofNullable(item.getTagDetails()).flatMap(list -> list.stream().findFirst()).map(GetWorkItemInfoResponseBody.TagDetails::getName).orElse(TAG_EMPTY);
                                    if (!StringUtils.hasText(tagName)) {
                                        tagName = TAG_EMPTY;
                                    }
                                    yxBug.setTagName(tagName);
                                    return yxBug;
                                }
                        ).collect(Collectors.toList());

                // 按照需求分组
                // mapFactory: 这是（Supplier），用于创建一个用于收集结果的Map实例。通常情况下，你可以使用LinkedHashMap::new、HashMap::new或TreeMap::new等来指定Map的具体类型。
                // 这是因为groupingBy的结果是一个Map，mapFactory决定了这个Map的具体实现类，从而影响了分组结果的存储方式（例如，保持插入顺序、自然排序等）
                // HashMap<String, HashMap<String, Map<String, Long>>> bigMap = bugList.stream().collect(Collectors.groupingBy(YxBug::getTagName, HashMap::new,
                //         Collectors.groupingBy(YxBug::getChargePerson, HashMap::new,
                //                 Collectors.groupingBy(YxBug::getStatus, Collectors.counting())
                //         )
                // ));
                Map<String, Map<String, Map<String, Integer>>> bigMap = bugList.stream().collect(Collectors.groupingBy(YxBug::getTagName,
                        Collectors.groupingBy(YxBug::getChargePerson,
                                Collectors.groupingBy(YxBug::getStatus, Collectors.summingInt(bug -> 1)) //Collectors.counting())
                        )));

                List<YxReqBug> reqBugList = bigMap.entrySet().stream().map(entry -> {
                    String reqName = entry.getKey();
                    Map<String, Map<String, Integer>> chargePersonMap = entry.getValue();
                    int bugCount = chargePersonMap.values().stream().flatMap(map -> map.values().stream()).mapToInt(y -> y).sum();

                    List<YxPersonBug> personBugList = chargePersonMap.entrySet().stream().map(mapEntry -> {
                        String personId = mapEntry.getKey();
                        String personName;
                        try {
                            personName = userCache.get(personId);
                        } catch (ExecutionException e) {
                            personName = USER_MAP.getOrDefault(personId, personId);
                        }

                        Map<String, Integer> statusMap = mapEntry.getValue();
                        int personBugCount = statusMap.values().stream().mapToInt(z -> z).sum();

                        List<YxStatusBug> statusBugList = statusMap.entrySet().stream()
                                .map(k -> new YxStatusBug(k.getKey(), k.getValue())).collect(Collectors.toList());

                        return new YxPersonBug(personName, personBugCount, statusBugList);
                    }).collect(Collectors.toList());

                    return new YxReqBug(reqName, bugCount, personBugList);
                }).collect(Collectors.toList());

                YxProjectBug projectBug = new YxProjectBug(spaceIdentifier, spaceName, count.intValue(), reqBugList);
                projectBugList.add(projectBug);
            }
        }
        long end = System.currentTimeMillis();
        log.info("====查询Bug耗时：{} 毫秒 ", (end - start));
        return projectBugList;
    }


    /**
     * 获得工作项的Response
     *
     * @param idList
     * @return
     */
    private List<GetWorkItemInfoResponse> getGetWorkItemInfoResponse(List<String> idList) {
        //根据ID查询详细信息
        List<CompletableFuture<GetWorkItemInfoResponse>> workItemResponseFutureList = Lists.newArrayList();

        for (String id : idList) {
            // Parameter settings for API request
            GetWorkItemInfoRequest getWorkItemInfoRequest = GetWorkItemInfoRequest.builder()
                    .organizationId(ORGANIZATION_ID)
                    .workitemId(id)
                    // Request-level configuration rewrite, can set Http request parameters, etc.
                    // .requestConfiguration(RequestConfiguration.create().setHttpHeaders(new HttpHeaders()))
                    .build();

            // Asynchronously get the return value of the API request
            CompletableFuture<GetWorkItemInfoResponse> responseCompletableFuture = asyncClient.getWorkItemInfo(getWorkItemInfoRequest);
            // 阿里云会限速不能频繁调用
            responseCompletableFuture.join();
            workItemResponseFutureList.add(responseCompletableFuture);
        }

        CompletableFuture<List<GetWorkItemInfoResponse>> workItemResponseList = CompletableFuture.allOf(workItemResponseFutureList.toArray(new CompletableFuture[0]))
                .thenApply(v -> workItemResponseFutureList.stream().map(CompletableFuture::join)
                        .filter(Objects::nonNull)
                        .collect(Collectors.toList()))
                .exceptionally(throwable -> {
                    throwable.printStackTrace();
                    return null;
                });
        return workItemResponseList.join();
    }


    public int getDayThreshold() {
        return dayThreshold.get();
    }

    public void setDayThreshold(int threshold) {
        if (threshold >= 7 && threshold <= 20) {
            dayThreshold.set(threshold);
            log.info("长期未启动的需求报告中阈值设置为：{}", threshold);
            String message = "长期未启动的需求跟踪报告中的时间阈值设置为" + threshold + "天";
            messageSender.sendMessage(message, Env.TEST);
        }
    }

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        // 创建一系列的CompletableFuture，每个都使用apiExecutor线程池
        int count = 5;
        CompletableFuture<?>[] futures = IntStream.range(0, count)
                .mapToObj(i -> CompletableFuture.runAsync(() -> {
                    System.out.println("Task " + i + " started by thread: " + Thread.currentThread().getName());
                    try {
                        // 模拟耗时操作
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                    System.out.println("Task " + i + " finished");
                }, apiExecutor))
                //toArray 是 Stream 接口的一个终止操作，用于将流中的元素收集到一个数组中
                // 方法引用 CompletableFuture[]::new 相当于一个无参构造器，它返回一个 CompletableFuture[] 类型的新数组
                .toArray(CompletableFuture[]::new);

        // 使用CompletableFuture.allOf()来等待所有任务完成
        CompletableFuture.allOf(futures).get(); // 这里会阻塞直到所有任务完成

        // 关闭线程池
        apiExecutor.shutdown();
    }

}
